package com.pbase.data.http.upanddown;

import com.blankj.utilcode.util.FileIOUtils;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.Utils;
import com.pbase.R;
import com.pbase.data.http.DataState;
import com.pbase.data.http.RetrofitBuilderTool;
import com.pbase.data.http.interceptor.ProgressInterceptor;
import com.pbase.data.http.listener.OnDataRequestListenerWithProgress;
import com.pbase.tools.Logger;

import java.io.File;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

import androidx.annotation.NonNull;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.observers.DisposableObserver;
import io.reactivex.rxjava3.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.http.GET;
import retrofit2.http.Streaming;
import retrofit2.http.Url;

/**
 * 文件下载实例生成
 */
public class DownRetrofitClient {

    private static Retrofit retrofit;
    private OnDataRequestListenerWithProgress listener;
    private DisposableObserver<InputStream> disposable;

    public DownRetrofitClient() {
    }


    public void retrofitClient(@NonNull RetrofitBuilderTool tool,
                               OnDataRequestListenerWithProgress listener) {
        this.listener = listener;
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectTimeout(tool.connectTimeout(), TimeUnit.SECONDS)
                .readTimeout(tool.readTimeout(), TimeUnit.SECONDS)
                .writeTimeout(tool.writeTimeout(), TimeUnit.SECONDS);
        ProgressInterceptor progressInterceptor = tool.buildProgressInterceptor(listener);
        if (progressInterceptor != null) {
            builder.addInterceptor(progressInterceptor);
        }
        OkHttpClient okHttpClient = builder.build();

        retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .baseUrl(tool.baseUrl())
                .build();
    }

    //文件下载，通过rxjava切换线程，先下载到临时文件再成功后重命名，结果于主线程返回，
    public void downLoad(String filePath, String url) {
        final String temp = filePath + ".det"; //临时文件
        Logger.d(getClass(), "temp:" + temp);
        disposable = new DisposableObserver<InputStream>() {
            @Override
            public void onNext(@NonNull InputStream inputStream) {
                new File(temp).renameTo(new File(filePath)); //重命名
                if (listener != null) {
                    listener.onRequestDataSuccess(null);
                }
            }

            @Override
            public void onError(@NonNull Throwable e) {
                if (listener != null) {
                    listener.onRequestDataFailed(DataState.ERR_DATA, Utils.getApp()
                            .getString(R.string.data_err_data));
                }
            }

            @Override
            public void onComplete() {
                if (listener != null) {
                    listener.done();
                }
            }
        };
        retrofit.create(DownServer.class).download(url)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .map(responseBody -> responseBody.byteStream())
                .observeOn(Schedulers.computation())
                .doOnNext(inputStream -> {
                    writeFile(inputStream, temp);
                }).observeOn(AndroidSchedulers.mainThread())
                .subscribe(disposable);


    }

    /**
     * 将输入流写入文件
     *
     * @param inputString
     * @param filePath
     */
    private void writeFile(InputStream inputString, String filePath) {
        File file = new File(filePath);
        FileUtils.createFileByDeleteOldFile(file);
        if (!FileIOUtils.writeFileFromIS(file, inputString)) {
            listener.onRequestDataFailed(DataState.ERR_DATA,
                    Utils.getApp().getString(R.string.data_err_data));
        }


    }

    /**
     * 停止下载
     */
    public void stopDown() {
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
        disposable = null;
    }


    private interface DownServer {
        @Streaming//表示请求的数据以流的形式返回；未使用该注解，默认会把数据全部载入内存
        @GET
        Observable<ResponseBody> download(@Url String url);
    }
}
